package com.iot.core.data.mapper;


import com.iot.core.data.BaseDto;
import com.iot.core.data.BaseEntity;
import com.iot.core.data.BasePageQto;
import com.iot.core.data.BaseQto;
import com.iot.core.exception.MyException;
import com.iot.core.manager.htcls.HtClsManager;
import com.iot.core.manager.id.HtIdManager;
import com.iot.core.springboot.MyThreadLocal;
import com.iot.core.util.StreamUtil;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;


public interface MyBaseMapper<T> extends BaseMapper<T> {
    default void  beforeInsert(T entity) throws  Exception{
        if(entity instanceof BaseEntity be){
            if(ObjectUtils.isEmpty(be.getId())||be.getId().toString().equals("0")){
                be.setId(HtIdManager.getInstance().nextLong());
            }
        }
        var su= MyThreadLocal.get().getSu();
        var mcls= HtClsManager.getInstance().findByFullName(entity.getClass().getName() );
        for(var f:mcls.getFields()){
            var EName=f.getEname();
            var FV=f.getField().get(entity);
            switch (EName){
                case "crtDt":
                case "edtDt":
                {
                    if(ObjectUtils.isEmpty(FV)){
                        f.getField().set(entity,new Date() );
                    }
                }
                break;
                case "crtUid":
                case "edtUid":
                {
                    if(ObjectUtils.isEmpty(FV)||FV.toString().equals("0")){
                        f.getField().set(entity,su.getCrtUid() );
                    }
                }
                break;
                case "crtDid":
                {
                    if(ObjectUtils.isEmpty(FV)||FV.toString().equals("0")){
                        f.getField().set(entity,su.getCrtDid() );
                    }
                }
                break;
                case "gid":
                {
                    if(ObjectUtils.isEmpty(FV)|| FV.toString().equals("")){
                        f.getField().set(entity,HtIdManager.getInstance().nextGuidStr()  );
                    }
                }
                default:
                {
                    switch (f.getLx()){
                        case "java.lang.String":
                        {
                            HtClsManager.getInstance().dealStrNullAndTrim(entity,f.getField() );
                        }
                        break;
                    }
                }
                break;
            }

        }
    }

    default void  beforeUpdate(T entity) throws  Exception{
        var su=MyThreadLocal.get().getSu();
        var mcls=HtClsManager.getInstance().findByFullName(entity.getClass().getName() );
        for(var f:mcls.getFields()){
            var EName=f.getEname();
            switch (EName)
            {
                case "edtUid":
                {
                    f.getField().set(entity,su.getCrtUid() );
                }
                break;
                case "edtDt":
                {
                    f.getField().set(entity,new Date() );
                }
                break;
                default:
                {
                    switch (f.getLx()){
                        case "java.lang.String":
                        {
                            HtClsManager.getInstance().dealStrNullAndTrim(entity,f.getField() );
                        }
                        break;
                    }
                }
                break;
            }

        }
    }
    @Override
    default   int insert(T entity  ){
        try {
            beforeInsert(entity);
        }
        catch (Exception ex){
            ex.printStackTrace();
        }
        var r= insert(entity,false);
        if(r>0){
            MyThreadLocal.get().setInserted(entity);
            MyThreadLocal.get().getInserteds().add(entity);
        }
        return r;
    }

    default   int updateById(T entity,boolean autoField ){
        var r=0;
        if(!autoField){
            r=  update(entity);
        }else{
            try {
                beforeUpdate(entity);
            }
            catch (Exception ex){
                ex.printStackTrace();
            }
            r= update(entity);
        }
        if(r>0){
            MyThreadLocal.get().setInserted(entity);
            MyThreadLocal.get().getInserteds().add(entity);
        }
        return r;
    }
    default   int deleteById(T entity,boolean autoField ){
        AtomicInteger r= new AtomicInteger();
        if(!autoField){
            r.set(delete(entity));
        }else{
            var bHaveDelete=HtClsManager.getInstance().hasField(entity,"deleted");
            if(bHaveDelete){
                var su=MyThreadLocal.get().getSu();
                HtClsManager.getInstance().setFieldV(entity,"deleted",true);
                HtClsManager.getInstance().setFieldV(entity,"edtUid",su.getCrtUid() );
                HtClsManager.getInstance().setFieldV(entity,"edtDt",new Date() );
                LogicDeleteManager.execWithoutLogicDelete(()->{
                   r.set(update(entity));
                });

            }
           else{
                r.set(delete(entity));
            }
        }
        if(r.get() >0){
            MyThreadLocal.get().setDeleted(entity);
            MyThreadLocal.get().getDeleteds().add(entity);
        }
        return r.get();
    }



    default <U> void entityToDto(T src, U dst)  {
//        final Map<String, Object> aProps = BeanUtils.describe(a);
//        final Map<String, Object> bProps = BeanUtils.describe(b);
//        aProps.keySet().retainAll(bProps.keySet());
//        for (Entry<String, Object> entry : aProps.entrySet()) {
//            BeanUtils.setProperty(b,entry.getKey(), entry.getValue());
//        }
        if (src == null || dst == null) {
            throw new MyException("不支持的对象");
        }
        var msrccls = HtClsManager.getInstance().findByFullName(src.getClass().getName());
        if (msrccls == null) {
            throw new MyException("不支持的对象");
        }
        var mdstcls = HtClsManager.getInstance().findByFullName(dst.getClass().getName());
        if (mdstcls == null) {
            throw new MyException("不支持的对象");
        }
        {
            var id=((BaseEntity)src).getId();
            if(dst instanceof BaseDto dst1){
                dst1.setId(id);
            }
            if(dst instanceof BaseEntity dst2){
                dst2.setId(id);
            }
        }
        for (var pdst : mdstcls.getFields()) {
            try{
                var psrc = StreamUtil.get(msrccls.getFields(), a -> a.getEname().equals(pdst.getEname()));
                if (psrc == null) {
                    continue;
                }
                if ("pwd".equals(pdst.getEname()) || "czpwd".equals(pdst.getEname())) {
                    continue;
                }
                var vsrc = psrc.getField().get(src);
                if (vsrc == null) {
                    continue;//null 强制跳过
                }

                pdst.getField().set(dst, vsrc);
            }
            catch (Exception ex){
                ex.printStackTrace();
            }

        }
    }
    default <U> void dtoToEntity(  U src,T dst)  {
        if (src == null|| dst==null)
        {
            throw new MyException("不支持的对象");
        }
        var msrccls = HtClsManager.getInstance().findByFullName(src.getClass().getName());
        if(msrccls == null)
        {
            throw new MyException("不支持的对象");
        }
        var mdstcls = HtClsManager.getInstance().findByFullName(dst.getClass().getName());
        if (mdstcls == null)
        {
            throw new MyException("不支持的对象");
        }

        {
            if(src instanceof BaseDto src1){
                if( dst instanceof  BaseEntity dst1){
                    dst1.setId(src1.getId() );
                }
            }

        }

        for (var pdst : mdstcls.getFields()) {
            try {
                var psrc = StreamUtil.get(msrccls.getFields(), a -> a.getEname().equals(pdst.getEname()));
                if (psrc == null) {
                    continue;
                }
                if ("crtDt".equals(pdst.getEname()) || "crtUid".equals(pdst.getEname())|| "crtDid".equals(pdst.getEname())) {
                    continue;
                }
                //插入 、修改时间不能更新
                if ("edtDt".equals(pdst.getEname()) || "edtUid".equals(pdst.getEname())  ) {
                    continue;
                }

                if ("pwd".equals(pdst.getEname()) || "czpwd".equals(pdst.getEname())) {
                    continue;
                }

                var vsrc = psrc.getField().get(src);
                if (vsrc == null&&!psrc.isNullable()) {
                    continue;//null 强制跳过
                }
                if (pdst.getEname().toString().equals("id"))
                {
                    if (vsrc.toString()=="0")
                    {
                        vsrc = HtIdManager.getInstance().nextLong() ;
                    }
                }
                pdst.getField().set(dst, vsrc);
            }
            catch (Exception ex){
                ex.printStackTrace();
            }
        }

    }


    default T getById(Long Id){
        return  selectOneById(Id);
    }
    default T getById(BaseQto mm){
        return getById(mm.getId() );
    }

    default Page<T> page(BasePageQto qm,QueryWrapper qw ) {
        Page<T> pg=new Page<>();
        pg.setPageNumber(qm.getPage() );
        pg.setPageSize(qm.getPageSize() );
        return paginate(pg,qw);
    }

    default <R> Page<R> pageAs(BasePageQto qm, QueryWrapper qw, Class<R> asType) {
        Page<R> page = new Page(qm.getPage(), qm.getPageSize());
        return paginateAs(  page, qw, asType );
    }
    default  QueryWrapper getQueryWrapper(){
        return new QueryWrapper();
    }

}
